// CHAPTER 6 OF OBJECT ORIENTED JAVASCRIPT
// INHERITANCE
mainchapter("6 INHERITANCE");

(function(){
	// 6.1 PROTOTYPE CHAINING
	chapter("6.1 PROTOTYPE CHAINING");
	try{
		function Shape(){
			this.name='shape';
			this.toString = function() {return this.name;};
		}
		function TwoDShape(){
			this.name = '2D shape';
		}
		function Triangle(side, height){
			this.name = 'Triangle';
			this.side = side;
			this.height = height;
			this.getArea = function(){return this.side * this.height / 2;};
		}
		TwoDShape.prototype = new Shape();
		Triangle.prototype = new TwoDShape();
		// prevent the negative side effects on the constructor
		TwoDShape.prototype.constructor = TwoDShape;
		Triangle.prototype.constructor = Triangle;
		var my = new Triangle(5,10);
		assertEquals(my.getArea(),25);
		assertEquals(my.toString(),"Triangle");
		success("6.1a Correct inheritance of methods and properties");
		assertEquals(my instanceof Triangle,true);
		assertEquals(my instanceof TwoDShape,true);
		assertEquals(my instanceof Shape,true);
		assertEquals(my instanceof Array,false);
		success("6.1b instanceof superclasses");
		assertEquals(Shape.prototype.isPrototypeOf(my),true);
		assertEquals(TwoDShape.prototype.isPrototypeOf(my),true);
		assertEquals(Triangle.prototype.isPrototypeOf(my),true);
		assertEquals(String.prototype.isPrototypeOf(my),false);
		success("6.1c superclass.isPrototypeOf(subclass) ");
	}catch(e){
		$ERROR("6.1 Prototype fail : "+e.message);
	}
})();

(function(){
	// 6.2 A TEMPORARY CONSTRUCTOR
	chapter("6.2 A TEMPORARY CONSTRUCTOR");
	try{
		function Shape(){}
		Shape.prototype.name='shape';
		Shape.prototype.toString = function(){return this.name;};
		function TwoDShape(){}
		// take care of inheritance
		var F = function(){}
		F.prototype = Shape.prototype;
		TwoDShape.prototype = new F();
		TwoDShape.prototype.constructor = TwoDShape;
		// augment prototype
		TwoDShape.prototype.name = '2D shape';

		function Triangle(side, height){
			this.side = side;
			this.height = height;
		}
		// take care of inheritance
		var F = function(){}
		F.prototype = TwoDShape.prototype;
		Triangle.prototype = new F();
		Triangle.prototype.constructor = Triangle;
		//augment prototype
		Triangle.prototype.getArea = function(){return this.side * this.height / 2;};
		Triangle.prototype.name = 'Triangle';
		
		var my = new Triangle(5,10);
		assertEquals(my.getArea(),25);
		assertEquals(my.toString(),"Triangle");
		success("6.2a Safe inheritance of method");
		var s = new Shape();
		assertEquals(s.name,"shape");
		Triangle.prototype.name = 'Triangle';
		assertEquals(s.name,"shape");
		success("6.2b Safe overwriting prototype property");
	}catch(e){
		$ERROR("6.2 With a temporary constructor: "+e.message);
	}
})();

(function(){
	// 6.3 UBER KEYWORD
	chapter("6.3 UBER KEYWORD");
	try{
		function Shape(){}
		Shape.prototype.name='shape';
		Shape.prototype.toString = function(){
			var result = [];
			if(this.constructor.uber){
				result[result.length] = this.constructor.uber.toString();
			}
			result[result.length] = this.name;
			return result.join(', ');
		};
		function TwoDShape(){}
		// take care of inheritance
		var F = function(){}
		F.prototype = Shape.prototype;
		TwoDShape.prototype = new F();
		TwoDShape.prototype.constructor = TwoDShape;
		TwoDShape.uber = Shape.prototype;
		// augment prototype
		TwoDShape.prototype.name = '2D shape';

		function Triangle(side, height){
			this.side = side;
			this.height = height;
		}
		// take care of inheritance
		var F = function(){}
		F.prototype = TwoDShape.prototype;
		Triangle.prototype = new F();
		Triangle.prototype.constructor = Triangle;
		Triangle.uber = TwoDShape.prototype;
		//augment prototype
		Triangle.prototype.name = 'Triangle';
		Triangle.prototype.getArea = function(){return this.side * this.height / 2;};
		
		var my = new Triangle(5,10);
		assertEquals(my.getArea(),25);
		assertEquals(my.toString(),"shape, 2D shape, Triangle");
		success("6.3 uber performed all super calls");
	}catch(e){
		$ERROR("6.3 uber shoud perform all super calls: "+e.message);
	}
})();

(function(){
	// 6.4 OBJECT CAPABILITY
	chapter("6.4 OBJECT CAPABILITY");
	try{
		// functions should not be in the global scope
		assertEquals(typeof Shape,"undefined");
		assertEquals(typeof TwoDShape,"undefined");
		assertEquals(typeof Triangle,"undefined");
		assertEquals(typeof my,"undefined");
		success("6.4 Previous declared functions are not in the global scope");
	}catch(e){
		$ERROR("6.4 With a temporary constructor: "+e.message);
	}
})();
